﻿using System;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Service.Validation;
using System.Collections.Generic;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Security.Authorization;

namespace Sinacor.Servico.Bovespa.Contabil.BusinessLogic
{
    /// <summary>
    /// BusinessLogic Class - ContaContabilFaturamento
    /// </summary>
    public class ContaContabilFaturamento : BaseBusinessLogic
    {
        #region Métodos Privados

        #region ValidarContaContabilFaturamento

        private void ValidarContaContabilFaturamento(BusinessEntity.ContaContabilFaturamento entity)
        {
            this.ValidarValor(entity);
            this.ValidarNegocioCredito(entity);
            this.ValidarNegocioDebito(entity);

            if (this.VerificarModuloContabilidadeInstalado())
            {
                if (new BusinessLogic.ContaContabil().ConsultarHistoricosContabeis(new BusinessEntity.Parameter.FiltroHistoricoContabil() { Codigo  = entity.CodigoHistoricoEstorno }).Count == 0)
                    throw new BusinessException(109318);
            }
        }

        #endregion

        #region ValidarExistenciaContaContabilFaturamento

        /// <summary>
        /// Validar existência de conta contábil
        /// </summary>
        /// <param name="parameter">BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave</param>
        /// <returns>Boolean</returns>
        private Boolean ValidarExistenciaContaContabilFaturamento(BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave parameter)
        {
            return this.ObterContaContabilFaturamento(parameter) != null;
        }

        #endregion        

        #region ValidarNegocioCredito

        private void ValidarNegocioCredito(BusinessEntity.ContaContabilFaturamento entity)
        {
            if (!this.VerificarModuloContabilidadeInstalado())
                return;

            List<BusinessEntity.PlanoConta> planoContas = new List<BusinessEntity.PlanoConta>();

            // Código Resumido e Dígito Crédito foram informados e a Conta Crédito não foi informada
            if (entity.CodigoResumidoCredito.HasValue && entity.DigitoResumidoCredito.HasValue && String.IsNullOrEmpty(entity.ContaCredito))
            {
                planoContas = new PlanoConta().ConsultarPlanosContas(new BusinessEntity.Parameter.FiltroPlanoConta()
                                                                                    {
                                                                                        CodigoResumidoConta = entity.CodigoResumidoCredito,
                                                                                        DigitoResumidoConta = entity.DigitoResumidoCredito
                                                                                    });

                if (planoContas.Count == 0)
                    throw new BusinessException(109376);
                else
                    entity.ContaCredito = planoContas[0].CodigoConta;
            }
            // Conta Crédito foi informada e o Código Resumido e Dígito não foram informados
            else if (!entity.CodigoResumidoCredito.HasValue && !entity.DigitoResumidoCredito.HasValue && !String.IsNullOrEmpty(entity.ContaCredito))
            {
                planoContas = new PlanoConta().ConsultarPlanosContas(new BusinessEntity.Parameter.FiltroPlanoConta()
                                                                                    {
                                                                                        CodigoConta = entity.ContaCredito
                                                                                    });

                if (planoContas.Count == 0)
                    throw new BusinessException(109377);
                else
                {
                    entity.CodigoResumidoCredito = planoContas[0].CodigoResumidoConta;
                    entity.DigitoResumidoCredito = planoContas[0].DigitoResumidoConta;
                }
            }
            // Código Resumido, Dígito e Conta Crédito foram informados
            else if (entity.CodigoResumidoCredito.HasValue && entity.DigitoResumidoCredito.HasValue && !String.IsNullOrEmpty(entity.ContaCredito))
            {
                planoContas = new PlanoConta().ConsultarPlanosContas(new BusinessEntity.Parameter.FiltroPlanoConta()
                                                                                    {
                                                                                        CodigoConta = entity.ContaCredito,
                                                                                        CodigoResumidoConta = entity.CodigoResumidoCredito,
                                                                                        DigitoResumidoConta = entity.DigitoResumidoCredito
                                                                                    });

                if (planoContas.Count == 0)
                    throw new BusinessException(109378);
            }

            // Verifica se código histórico informado é válido
            if (new BusinessLogic.ContaContabil().ConsultarHistoricosContabeis(new BusinessEntity.Parameter.FiltroHistoricoContabil() 
                                                                                            {
                                                                                                Codigo = entity.CodigoHistoricoCredito,
                                                                                                Digito = entity.DigitoHistoricoCredito
                                                                                            }).Count == 0)
                throw new BusinessException(109317);
        }

        #endregion

        #region ValidarNegocioDebito

        private void ValidarNegocioDebito(BusinessEntity.ContaContabilFaturamento entity)
        {
            if (!this.VerificarModuloContabilidadeInstalado())
                return;

            List<BusinessEntity.PlanoConta> planoContas = new List<BusinessEntity.PlanoConta>();

            // Código Resumido e Dígito Débito foram informados e a Conta Débito não foi informada
            if (entity.CodigoResumidoDebito.HasValue && entity.DigitoResumidoDebito.HasValue && String.IsNullOrEmpty(entity.ContaDebito))
            {
                planoContas = new PlanoConta().ConsultarPlanosContas(new BusinessEntity.Parameter.FiltroPlanoConta()
                                                                                    {
                                                                                        CodigoResumidoConta = entity.CodigoResumidoDebito,
                                                                                        DigitoResumidoConta = entity.DigitoResumidoDebito
                                                                                    });

                if (planoContas.Count == 0)
                    throw new BusinessException(109379);
                else
                    entity.ContaDebito = planoContas[0].CodigoConta;
            }
            // Conta Débito foi informada e o Código Resumido e Dígito não foram informados
            else if (!entity.CodigoResumidoDebito.HasValue && !entity.DigitoResumidoDebito.HasValue && !String.IsNullOrEmpty(entity.ContaDebito))
            {
                planoContas = new PlanoConta().ConsultarPlanosContas(new BusinessEntity.Parameter.FiltroPlanoConta()
                                                                                    {
                                                                                        CodigoConta = entity.ContaCredito
                                                                                    });

                if (planoContas.Count == 0)
                    throw new BusinessException(109380);
                else
                {
                    entity.CodigoResumidoDebito = planoContas[0].CodigoResumidoConta;
                    entity.DigitoResumidoDebito = planoContas[0].DigitoResumidoConta;
                }
            }
            // Código Resumido, Dígito e Conta Débito foram informados
            else if (entity.CodigoResumidoDebito.HasValue && entity.DigitoResumidoDebito.HasValue && !String.IsNullOrEmpty(entity.ContaDebito))
            {
                planoContas = new PlanoConta().ConsultarPlanosContas(new BusinessEntity.Parameter.FiltroPlanoConta()
                {
                    CodigoConta = entity.ContaDebito,
                    CodigoResumidoConta = entity.CodigoResumidoDebito,
                    DigitoResumidoConta = entity.DigitoResumidoDebito
                });

                if (planoContas.Count == 0)
                    throw new BusinessException(109378);
            }

            // Verifica se código histórico informado é válido
            if (new BusinessLogic.ContaContabil().ConsultarHistoricosContabeis(new BusinessEntity.Parameter.FiltroHistoricoContabil()
            {
                Codigo = entity.CodigoHistoricoDebito,
                Digito = entity.DigitoHistoricoDebito
            }).Count == 0)
                throw new BusinessException(109323);
        }

        #endregion        

        #region ValidarValor

        /// <summary>
        /// Valida Valor
        /// </summary>
        /// <param name="entity">BusinessEntity.ContaContabilFaturamento</param>
        private void ValidarValor(BusinessEntity.ContaContabilFaturamento entity)
        {
            SinacorValidation validation = new SinacorValidation();
            validation.Validate<BusinessEntity.ContaContabilFaturamento>(entity);

            if (!entity.CodigoGrupoContabil.HasValue)
                throw new BusinessException(109303);

            if (!entity.CodigoEventoContabil.HasValue)
                throw new BusinessException(109304);

            BusinessEntity.EventoContabil eventoContabil = new EventoContabil().ObterEventoContabil(new BusinessEntity.Parameter.FiltroEventoContabilChave(entity.CodigoEventoContabil.Value));

            if (eventoContabil.UtilizaMunicipio.HasValue && eventoContabil.UtilizaMunicipio.Value)
            {
                if (!entity.CodigoMunicipio.HasValue && entity.CodigoMunicipio.Value != null)
                {
                    throw new BusinessException(109305);
                }
            }
            else
            {
                entity.CodigoMunicipio = new Municipio().ObterMenorCodigoMunicipio();
            }

            if (!entity.CodigoHistoricoCredito.HasValue)
                throw new BusinessException(109306);

            if (!entity.CodigoHistoricoDebito.HasValue)
                throw new BusinessException(109307);

            if (!entity.CodigoHistoricoEstorno.HasValue)
                throw new BusinessException(109308);

            if (!entity.CodigoResumidoCredito.HasValue && !entity.DigitoResumidoCredito.HasValue && String.IsNullOrEmpty(entity.ContaCredito))
                throw new BusinessException(109309);

            if (!entity.CodigoResumidoDebito.HasValue && !entity.DigitoResumidoDebito.HasValue && String.IsNullOrEmpty(entity.ContaDebito))
                throw new BusinessException(109310);
        }

        #endregion

        #region VerificarModuloContabilidadeInstalado

        private Boolean VerificarModuloContabilidadeInstalado()
        {
            return (new Sinacor.Servico.Bovespa.Acesso.BusinessLogic.Acesso()).VerificarSistemaInstalado("CTB");
        }

        #endregion

        #endregion

        #region Métodos Públicos

        #region AlterarContaContabilFaturamento

        /// <summary>
        /// Altera Conta Contábil Faturamento
        /// </summary>
        /// <param name="entity">BusinessEntity.ContaContabilFaturamento</param>
        public void AlterarContaContabilFaturamento(BusinessEntity.ContaContabilFaturamento entity)
        {
            this.ValidarContaContabilFaturamento(entity);
            
            new ResourceAccess.ContaContabilFaturamento().AlterarContaContabilFaturamento(entity);
        }

        #endregion

        #region AlterarContasContabeisFaturamento

        /// <summary>
        /// Altera Conta Contábil Faturamento
        /// </summary>
        /// <param name="entityList">Lista de objetos do tipo BusinessEntity.ContaContabilFaturamento</param>
        public void AlterarContasContabeisFaturamento(List<BusinessEntity.ContaContabilFaturamento> entityList)
        {
            foreach(BusinessEntity.ContaContabilFaturamento entity in entityList)
                this.AlterarContaContabilFaturamento(entity);
        }

        #endregion

        #region ConsultarContasContabeisFaturamento

        /// <summary>
        /// Consulta contas contábeis faturamento
        /// </summary>
        /// <param name="parameter">Parameter.FiltroContaContabilFaturamento</param>
        /// <returns>Lista de objetos do tipo BusinessEntity.ContaContabilFaturamento</returns>
        public List<BusinessEntity.ContaContabilFaturamento> ConsultarContasContabeisFaturamento(BusinessEntity.Parameter.FiltroContaContabilFaturamento parameter)
        {
            return new ResourceAccess.ContaContabilFaturamento().ConsultarContasContabeisFaturamento(parameter);
        }

        #endregion

        #region ExcluirContaContabilFaturamento

        /// <summary>
        /// Exclui conta contábil faturamento
        /// </summary>
        /// <param name="parameter">BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave</param>
        public void ExcluirContaContabilFaturamento(BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave parameter)
        {
            if (parameter == null)
                throw new BusinessException(109301);

            new ResourceAccess.ContaContabilFaturamento().ExcluirContaContabilFaturamento(parameter);
        }

        #endregion

        #region ExcluirContasContabeisFaturamento

        /// <summary>
        /// Exclui contas contábeis faturamento
        /// </summary>
        /// <param name="parameterList">Lista de objetos do tipo BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave</param>
        public void ExcluirContasContabeisFaturamento(List<BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave> parameterList)
        {
            foreach(BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave parameter in parameterList)
                this.ExcluirContaContabilFaturamento(parameter);
        }

        #endregion

        #region IncluirContaContabilFaturamento

        /// <summary>
        /// Inclui conta contábil faturamento
        /// </summary>
        /// <param name="entity">BusinessEntity.ContaContabilFaturamento</param>
        public void IncluirContaContabilFaturamento(BusinessEntity.ContaContabilFaturamento entity)
        {
            this.ValidarContaContabilFaturamento(entity);

            if (this.ValidarExistenciaContaContabilFaturamento(new BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave()
            {
                CodigoBolsa = entity.CodigoBolsa,
                CodigoGrupoContabil = entity.CodigoGrupoContabil,
                CodigoEventoContabil = entity.CodigoEventoContabil,
                CodigoMunicipio = entity.CodigoMunicipio
            }))
                throw new BusinessException(109319);
            else
                new ResourceAccess.ContaContabilFaturamento().IncluirContaContabilFaturamento(entity);
        }

        #endregion

        #region IncluirContasContabeisFaturamento

        /// <summary>
        /// Inlcui contas contábeis faturamento
        /// </summary>
        /// <param name="entityList">Lista de objetos do tipo BusinessEntity.ContaContabilFaturamento</param>
        public void IncluirContasContabeisFaturamento(List<BusinessEntity.ContaContabilFaturamento> entityList)
        {
            foreach (BusinessEntity.ContaContabilFaturamento entity in entityList)
                this.IncluirContaContabilFaturamento(entity);
        }

        #endregion

        #region ObterContaContabilFaturamento

        /// <summary>
        /// Obtem conta contábil faturamento
        /// </summary>
        /// <param name="parameter">BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave</param>
        /// <returns>BusinessEntity.ContaContabilFaturamento</returns>
        public BusinessEntity.ContaContabilFaturamento ObterContaContabilFaturamento(BusinessEntity.Parameter.FiltroContaContabilFaturamentoChave parameter)
        {
            List<BusinessEntity.ContaContabilFaturamento> result = this.ConsultarContasContabeisFaturamento(new BusinessEntity.Parameter.FiltroContaContabilFaturamento()
                                                                                                            {
                                                                                                                CodigoBolsa = parameter.CodigoBolsa,
                                                                                                                CodigoEventoContabil = parameter.CodigoEventoContabil,
                                                                                                                CodigoGrupoContabil = parameter.CodigoGrupoContabil,
                                                                                                                CodigoMunicipio = parameter.CodigoMunicipio
                                                                                                            });

            if (result.Count == 0)
                return null;
            else
                return result[0];
        }

        #endregion

        #endregion
    }
}
